//select用于监听多个文件描述符

#pragma once
#include <iostream>
#include <string>
#include "Socket.hpp"
#include <memory>
#include "Log.hpp"
#include <poll.h>
#include "Common.hpp"
using namespace SocketModule;
using namespace LogModule;

#define MAX 4096

class PollServer
{
public:
    PollServer(int port)
    :_port(port)
    ,_listen_socket(std::make_unique<TcpSocket>())
    ,_isrunning(false)
    {}

    void Init()
    {
        _listen_socket->BuildTcpSocketMethod(_port);
        for(int i=0; i<MAX; i++)
        {
            _fds[i].fd = gdefaultsockfd;
            _fds[i].events = 0;
            _fds[i].revents = 0;
        }
        
        _fds[0].fd = _listen_socket->Fd();
        _fds[0].events |= POLLIN;
    }

    void Loop()
    {
        _isrunning=true;
        while(_isrunning)
        {
            int timeout = -1;
            int n=poll(_fds,MAX,timeout);
            switch(n)
            {
            case 0:
                std::cout<<"timeout"<<std::endl;
                break;
            case -1:
                std::cout<<"poll error"<<std::endl;
                break;
            default:
                std::cout<<"有事件就绪了" <<std::endl;
                Dispatcher();
                break;
                

            }
        }

        _isrunning=false;


    }

    void Dispatcher()//将listen套接字文件描述符和其余普通套接字一起交由select监听，再分发
    {
        for(int i=0;i<MAX;i++)
        {
            if(_fds[i].fd == gdefaultsockfd)
            {
                continue;
            }
            else
            {
                if(_fds[i].fd == _listen_socket->Fd())
                {
                    if(_fds[i].revents & POLLIN)
                    {
                        Accept();
                    }
                } 
                else
                {
                    if(_fds[i].revents & POLLIN)
                    {
                        Recver(i);
                    }
                }



            }
        }

    }

    void Accept()
    {
        InetAddr client;
        int newfd= _listen_socket->Accepter(&client);//第一次绝不会阻塞，但是我也只accep一次，第二次可能阻塞，哪怕有更多我也只弄一次

        if(newfd<0)
        {
            return ;
        }
        else
        {
            int i=0;
            for(; i<MAX ;i++)
            {
                if(_fds[i].fd != gdefaultsockfd)
                {
                    continue;
                }
                else
                {
                    _fds[i].fd=newfd;
                    _fds[i].events |=POLLIN;
                    break;
                }
            }

            if(i==MAX)
            {
                std::cout<<"POLL满了"<<std::endl;
                ::close(newfd);
            }

        }
    }

    void Recver(int i)
    {
        char buffer[1024];
        ssize_t n=recv(_fds[i].fd,buffer,sizeof(buffer)-1,0);
        if(n==0)
        {
            std::cout<<"tcp 断开"<<std::endl;
            close(_fds[i].fd);
            _fds[i].fd=gdefaultsockfd;
            _fds[i].events= _fds[i].revents=0;


        }
        else if(n>0)
        {
            buffer[n]=0;
            std::string s="echo# ";
            s+=buffer;
            ::send(_fds[i].fd,s.c_str(),s.size(),0);
        }
        else
        {
            std::cout<<"recv error"<<std::endl;
            close(_fds[i].fd);
            _fds[i].fd=gdefaultsockfd;
            _fds[i].events= _fds[i].revents=0;


        }

    }

private:
    uint16_t _port;
    std::unique_ptr<Socket> _listen_socket;
    bool _isrunning;
    struct pollfd _fds[MAX];


};